﻿////////////////////////////////////////////////////////////
//  Точки входа среды моделирования
//  Василий Кудрявцев
//  20 декабря 2008 года
//

#light

namespace Fp

module public FpInterperter

open FpCore
open Fp_parser
open Fp_lexer
open FpEval
open FpEvalStep
open Printf
open Microsoft.FSharp.Compatibility.OCaml
open System
open System.Collections.Generic


let rec step_by_step  line =
    let result, rule = step line 
    if (result <> line) then
       (result, rule) :: step_by_step result
    else
     [line, String.Empty]


and eval_cmd comd = 
  try
    match comd with
    | Def(s,f) ->  if add_user_def s f then  "Функция определена" else "Функция переопределена"
    | Undef s  -> (try del_user_def s; "Определение удалено" with Not_found -> "Определение не найдено")
    | Show s   -> (try if s = "all" then Seq.fold (fun splitter (kvp : KeyValuePair<string, fct>) ->  sprintf  "%s = %s\n" kvp.Key (string_of_fct kvp.Value)) ""  defs; else string_of_fct (get_user_def s); with Not_found -> "Определение не найдено")
    | Exp e    -> string_of_expr (eval e);
    
  with 
  | Eval_error e -> sprintf  "Ошибка: неизвестная функция: %s\n" (string_of_expr e); 
  | Eval_bottom e -> sprintf "Ошибка вычисления: %s\n" (string_of_expr e); 


and eval_cmd_step comd = 
  try
    match comd with
    | Def(s,f) -> if add_user_def s f then  "Функция определена" else "Функция переопределена"
    | Undef s  -> (try del_user_def s; "Определение удалено" with Not_found -> "Определение не найдено")
    | Show s   -> (try if s = "all" then Seq.fold (fun  splitter (kvp : KeyValuePair<string, fct>) ->  sprintf  "%s = %s\n" kvp.Key (string_of_fct kvp.Value)) "" defs ; else string_of_fct (get_user_def s); with Not_found -> "Определение не найдено")
    | Exp e    -> List.fold_left (fun s1 s2 -> s1^ "##" ^ s2)  "" (List.map (fun (a, b) -> b ^ "##" ^ a) (step_by_step (string_of_expr e)) );
    
  with 
  | Eval_error e -> sprintf  "Ошибка: неизвестная функция: %s\n" (string_of_expr e)
  | Eval_bottom e -> sprintf "Ошибка вычисления: %s\n" (string_of_expr e)
;



let exe line = eval_cmd(cmd lexer (Lexing.from_string line));
let exe_step line = eval_cmd_step (cmd lexer (Lexing.from_string line));